#include "../include/teclado.h"
#include "../include/string.h"
#include "../include/stdio.h"
#include "../include/pantalla.h"
#include "../include/interrupciones.h"
#include "../include/kernel.h"


/*
 * Inicializa el driver del teclado, las variables que se utilizan y el File Descriptor
 */
void inicializarTeclado()
{
	shift=1;					// inicializa la variable shift. 1=minusculas;0=mayusculas

	teclado=open(STDIN);
	teclado->dir=bufferTeclado;	// inicializa el File Descriptor apuntandolo al buffer de teclado
	restartTeclado();			// vacía el buffer y setea en 0 los cursores
}

/*
 * Vacia el buffer de teclado y setea en 0 los cursores de lectura y escritura
 */
void restartTeclado()
{
	teclado->cursorW=0;
	teclado->cursorR=0;
	teclado->dir[teclado->cursorW]=0;
}

/*
 * Agrega el caracter al buffer de teclado, lo imprime e imprime el cursor grafico a continuacion
 */
void agregarABuffer(char ascii)
{
	if (ascii=='\b')
	{
		if (teclado->cursorW!=0)		// si es un BackSpace y hay caracteres para borrar,
		{								// borra el caracter graficamente y logicamente del buffer
			putchar(ascii);
			imprimirCursor();
			teclado->dir[--(teclado->cursorW)]=0;
		}
	}
	else
	{
		if (teclado->cursorW<=BUFFER_TECLADO-2 || ascii=='\n')	// si hay espacio en el buffer o
		{														// es un enter (se procesa siempre)
			teclado->dir[(teclado->cursorW)++]=ascii;	// agrego el caracter al buffer
			teclado->dir[teclado->cursorW]=0;
			putchar(ascii);								// imprimo el caracter
			imprimirCursor();
		}
	}
}

/*
 * Procesa la interrupcion del teclado. Recibo como parametro el codigo que genera el teclado
 */
void procTeclado(unsigned int code)
{
	// reactivo la pantalla en caso de ser necesario y vuelvo a 0 el contador
	if (!reactivarSalvaPantalla())	// si no estaba habilitado el salvapantalla proceso la tecla
	{
		switch(code)
		{
			case LEFT_MAKE_SHIFT:
			case RIGHT_MAKE_SHIFT:
			case RIGHT_BREAK_SHIFT:
			case LEFT_BREAK_SHIFT:
			case MAKE_BLOCK_MAYUS:
				shift = !shift;
				break;
			default:
				if(!( code & 0x80 ))  //solo proceso cuando se pulsa la tecla, no cuando se suelta
					procAscii(ScanCodes[code][shift]);	// obtengo el codigo ascii y llamo a procAscii
				break;
		}
	}
}

void procAscii(char ascii)
{
	char buf[BUFFER_TECLADO];

	buf[0]=0;
	if (ascii!=NADA)			// si el ascii es imprimible
	{
		agregarABuffer(ascii);	// lo agrego al buffer (adentro lo imprime)
		if (ascii=='\n')
		{						// si es un Enter leo la linea del buffer, proceso el comando y
			getLine(buf);		// vuelvo a imprimir el prompt
			procesaComando(buf);
			prompt();
		}
	}
}

/*
 * Parsea el comando y los parametros y ejecuta la accion correspondiente
 */
void procesaComando(char *str)
{
	char comando[100];
	char parametro[100];
	char parametros[10][100];
	int param;
	int i=0,j=0;
	int cantParam=0;
	int dir=0;
	DESCR_SEG segmento;

	if (strlen(str)>100)
	{
		printf("El comando es demasiado largo\n");
		return;
	}

	while(str[i]!=' ' && str[i]!='\0') 		// parseo el comando
	{
		comando[i]=str[i];
		i++;
	}
	comando[i]='\0';

	if (strcmp(comando,"salvapantalla")==0)	// si el comando es "salvapantalla"
	{
		if (str[i]==' ' && str[i+1]!=0)
		{
			i++;
			while(str[i]!=0)				// parseo el parametro
				parametro[j++]=str[i++];

			parametro[j]=0;
			param=stringToInt(parametro);	// lo convierto a entero
			if (param==-1 || param==0)
				printf("El parametro del comando SALVAPANTALLA debe ser un numero natural.\n");
			else
			{
				asignarEsperaSalvaPantalla(param);
				printf("Cambio el salvapantallas a %d segundos (en bochs dividilo por 3)\n",param);
			}
		}
		else
		{
			printf("Falta Ingresar un parametro\n");
		}
	}
	else if (strcmp(comando,"help")==0)	// si el comando es "help"
	{
		printf("\nEsto es una prueba de texto para hacer copy & paste usando el mouse. \n");
		printf("Para copiar el texto ubique el mouse donde quiere comenzar la seleccion, presione click izquierdo y arrastre el mouse hasta donde desea terminar la seleccion. El area de seleccion es un rectangulo.\n");
		printf("Para pegar el texto copiado, hacer click derecho con el mouse. El texto se pegara en la posicion del cursor de teclado.\n\n");

	}
	else if (strcmp(comando, "listarSegmento")==0) // el comando es segmento
	{
		printGDT();
		printf("Aca tiene que mostrar los segmentos que estan cargados!\n");
	}
	else if (strcmp(comando, "agregarSegmento")==0) // el comando es agregar un segmento
	{
		if (str[i]==' ' && str[i+1]!=0)
		{
			i++;
			while(str[i]!=0)				// parseo el parametro
			{
				if(str[i]==' ')
				{
					parametros[cantParam][j++]=='0'; //PONGO EL \0
					cantParam=cantParam++;
					j=0;
				}

				parametros[cantParam][j++]=str[i++];
			}
			parametros[cantParam][j++]=='0'; //al ultimo parametro le pone el \0

			//HAY QUE CHEQUEAR QUE CANTPARAM SEA IGUAL A LA CANTIDAD DE PARAMETROS
			//CONVERTIRLOS A ENTEREO CON STRINGTOINT
			//LLAMAR A LA FUNCION QUE SE ENCARGUE DE PONER EL SEGMENTO EN MEMORIA.
			//SI NO ES VALIDO HACER UN PRINTF

			/*
			stringToInt(parametros[0]); //aca esta la base (32 bits)
			stringToInt(parametros[1]); //aca esta el limite (16 bits)
			stringToInt(parametros[2]); //aca esta el access (8 bits)
			stringToInt(parametros[3]); //aca esta el atributos (8 bit)
			*/

			if (cantParam!=4)
				printf("Tiene que ingresar 4 parametros para agregar segmento\n");
			else
			{
				if (dir=stringToInt(parametros[0])>255)
				{
					printf("El segmento tiene que estar entre 0 y 255");
				}
				gdt_set_gate(&gdt[dir], (long)stringToInt(parametros[1]), (word)stringToInt(parametros[2]), parametros[3], parametros[4]);
				printf("Segmento cargado a la GDT.\n");
			}
		}
		else
		{
			printf("Falta Ingresar un parametro\n");
		}
	}
	else if (comando[0]!=0) // si no es ningun comando valido y no es solo un enter imprimo error
	{
		printf("Comando invalido\n");
	}
}
